import Vue from "vue";
import axios from "axios";
import Bus from "./Bus";
import { Message } from "element-ui";
import { Loading } from "element-ui";
import VueCookie from "vue-cookies";
import { sm3encrypt } from "./smUtil";
import { v4 as uuidv4 } from "uuid";
const stringify = require("json-stable-stringify");

Vue.use(VueCookie);
let $cookie = VueCookie;
let loading = ""; //定义loading变量
let message = null;

function startLoading() {
  //使用Element loading-start 方法
  loading = Loading.service({
    lock: false,
    text: "加载中，请稍后...",
    spinner: "el-icon-loading",
    background: "rgba(0, 0, 0, 0.3)"
  });
}
function endLoading() {
  //使用Element loading-close 方法
  loading.close();
}
const getParamsString = params => {
  const sortedKeys = Object.keys(params).sort(); // 对键进行字母排序
  let queryString = sortedKeys.map(key => `${key}=${params[key]}`).join('&');
  return queryString;
};
axios.defaults.timeout = 200000;
//http request 拦截器
axios.interceptors.request.use(
  config => {
    const timestamp = new Date().getTime();
    let params,
      s = "";
    if (config.method == "get") {
      params = stringify(config.params);
      params = getParamsString(JSON.parse(params));
      if (params == null || params == "") {
        params = "{}";
      }
      // console.log("加密前", params + "-timestamp=" + timestamp);
      s = sm3encrypt(params + "-timestamp=" + timestamp);
      // console.log("加密后", s);
    } else {
      params = stringify(config.data);
      // console.log("加密前", params + "-timestamp=" + timestamp);
      s = sm3encrypt(params + "-timestamp=" + timestamp);
    }
    // console.log("s", s);
    config.headers["Timestamp"] = timestamp;
    config.headers["X-Nonce"] = uuidv4().replace(/-/g, "");
    config.headers["Signature"] = s;
    if (config.url) {
      if (
        config.url.indexOf("techniqueDevelopmentTrend") > 0 ||
        config.url.indexOf("technologyGlobalDistribution") > 0 ||
        config.url.indexOf("technicalDomainDistribution") > 0 ||
        config.url.indexOf("technologyEntityRanking") > 0 ||
        config.url.indexOf("technicalExpertsRanking") > 0
      ) {
        startLoading();
      }
    }

    let token = $cookie.get("token");
    if (token) {
      config.headers["Authorization"] = token;
    }
    return config;
  },
  error => {
    if (loading && loading !== "") {
      endLoading();
    }
    return new Promise(() => { });
  }
);

// http response 拦截器
axios.interceptors.response.use(
  response => {
    let data = response.data;
    // Bus.$emit("showLoginDialog", true)
    if (loading && loading !== "") {
      endLoading();
    }
    if (response.headers?.authorization) {
      // document.cookie = "token=" + response.headers.authorization;
      $cookie.set("token", response.headers.authorization);
    }
    let code = data.code || data.status;
    if (code == 401) {
      // token失效,过期
      // console.log("token失效")
      $cookie.remove("token");
      // $cookie.set("token", "");
      Bus.$emit("showLoginDialog", true);
      Message({
        message: data.msg || data.message || "接口错误，请联系管理员！",
        type: "warning"
      });
      return new Promise(() => { });
    } else if (response.status == 500) {
      Message({
        message: data.msg || data.message || "接口错误，请联系管理员！",
        type: "warning"
      });
      return new Promise(() => { });
    } else if (code == 40307) {
      // token即将失效
      $cookie.set("token", data.data.token);
      //重新请求
      return axios(response.config);
    } else if (code == 40305) {
      if (!message) {
        message = Message({
          type: "error",
          showClose: true,
          dangerouslyUseHTMLString: true,
          duration: 3000,
          message: `<p style="line-height:20px;">试用账号无法查看，请联系管理员开通正式账号，联系方式 010-53223695<br>
            <a href='#/search/white'>点击此处返回试用公司列表</a></p>`
        });
      }
      return response;
    } else if (code == 200 || code == 40310) {
      // console.log("response", response);
      return response;
    } else if (code == 403 || code == 500 || code == 503) {
      Message({
        message: data.msg || data.message || "接口错误，请联系管理员！",
        type: "warning"
      });
      return Promise.reject(response);
    } else {
      return response;
    }
  },
  error => {
    if (loading && loading !== "") {
      endLoading();
    }
    if (axios.isCancel(error)) {
      // 为了终结promise链 就是实际请求 不会走到.catch(rej=>{});这样就不会触发错误提示之类了。
      return new Promise(() => { });
    } else {
      return Promise.reject(error);
    }
  }
);

/**
 * 封装get方法
 * @param url
 * @param data
 * @returns {Promise}
 */

export function get(url, params = {}, cancel) {
  return new Promise((resolve, reject) => {
    axios
      .get(url, {
        params: params,
        cancelToken: cancel
      })
      .then(response => {
        resolve(response.data);
      })
      .catch(err => {
        reject(err);
      });
  });
}

/**
 * 封装get blob方法
 * @param url
 * @param data
 * @returns {Promise}
 */
export function getBlob(url, params = {}, cancel) {
  return new Promise((resolve, reject) => {
    axios
      .get(url, {
        responseType: "blob",
        params: params,
        cancelToken: cancel
      })
      .then(
        response => {
          resolve(response);
        },
        err => {
          reject(err);
        }
      );
  });
}

/**
 * 封装post请求
 * 例如导出报告等 需要就将 responseType: 'blob', 流的类型放进第三个参数
 * @param url
 * @param data
 * @returns {Promise}
 */

export function post(url, data = {}, config = {}) {
  return new Promise((resolve, reject) => {
    axios
      .post(url, data, config)
      .then(response => {
        resolve(response.data);
      })
      .catch(err => {
        reject(err);
      });
  });
}

/**
 * 封装put方法
 * @param url
 * @param data
 * @returns {Promise}
 */

export function put(url, data = {}) {
  return new Promise((resolve, reject) => {
    axios
      .put(url, data)
      .then(response => {
        resolve(response.data);
      })
      .catch(err => {
        reject(err);
      });
  });
}

/**
 * 封装delete方法
 * @param url
 * @param data
 * @returns {Promise}
 */

export function axiosDelete(url, params = {}) {
  return new Promise((resolve, reject) => {
    axios
      .delete(url, {
        params: params
      })
      .then(response => {
        resolve(response.data);
      })
      .catch(err => {
        reject(err);
      });
  });
}
